#ifndef CPP_VIEW_H
#define CPP_VIEW_H

#include <Bitmap.h>
#include <BitmapFactory.h>
#include <Display.h>
#include <Global.h>
#include <MiniGui.h>
#include <Point.h>
#include <KeyEvent.h>
#include <MotionEvent.h>
#include <utils/Timer.h>
#include <atomic>

typedef enum {
    TEXT_ALIGN_NONE = 0x00,
    TEXT_ALIGN_LEFT = 0x01,
    TEXT_ALIGN_RIGHT = 0x02,
    TEXT_ALIGN_TOP = 0x04,
    TEXT_ALIGN_TOP_LEFT = TEXT_ALIGN_TOP | TEXT_ALIGN_LEFT,
    TEXT_ALIGN_COUNT
}
TextAlignStyle;

#define VIEW_DEAFAULT_ACC 30
#define VIEW_SETTLING_SPPED_MIN 600 //触发惯性滑动的最小速度

const std::string RX_VIEW = "RX_VIEW";
typedef enum {
    MSG_KEY_EVENT = MSG_USER + 1,
    MSG_ON_CLICK_EVENT,
    MSG_HANDLER,
    MSG_INVALIDATE_EVENT,
    MSG_STATUS_CHANGED_EVENT,
    MSG_ACTIVITY_CONTROL,
    MSG_VIEW_DELETE,
    MSG_SYSTEM_SLEEP,
    MSG_VIEW,
} CUSTOM_MSG;

class Canvas;
class Rect;
class Bitmap;
class ViewGroup;
class ScrollView;

//@brief 基础视图抽象类
//@author cvte
class View : public KeyEvent::Callback {
   public:
    static const int INVISIBLE = 0x00000001;
    static const int VISIBLE = 0x00000002;
    static const int CLICKABLE = 0x00004000;
    static const int DIRECTION_VERTICAL = 0x00000000;
    static const int DIRECTION_HORIZONTAL = 0x00000001;

    static const int SCROLL_NONE = 0x00;
    static const int SCROLL_UP = 0x01;
    static const int SCROLL_DOWN = 0x02;
    static const int SCROLL_LEFT = 0x03;
    static const int SCROLL_RIGHT = 0x04;

    static const int SCROLL_STATE_IDLE = 0x00; //空闲状态
    static const int SCROLL_STATE_DRAGGING = 0x01; //滑动状态
    static const int SCROLL_STATE_SETTLING = 0x02; //滑动后滑翔的状态
    friend class ViewGroup;
    friend class ScrollView;
    class OnTouchListener {
       public:
        virtual void onTouch(View& view, MotionEvent& event);
    };

    class OnClickListener {
       public:
        virtual void onClick(View& view);
    };
    View();
    virtual ~View();
    //创建窗口方法，派生类必须实现
    virtual void create(HWND parent);
    virtual View* getClassType();
    virtual bool containView(View* view);
    virtual void eraseView(View* view);

    HWND getParentHWND();
    HWND getHWND();
    void setParent(View& parent);
    View* getParent();
    Canvas* getCanvas();
    void setSize(int x, int y, int w, int h);
    void setX(int x);
    void setY(int y);
    int getX();
    int getY();
    //@method 获取绝对坐标X
    int getAbsX();
    //@method 获取绝对坐标Y
    int getAbsY();
    int getWidth();
    int getHeight();
    //获取实际矩形区域
    Rect getRealRect();
    //@method 将背景模糊，目前仅在View和ViewGroup上有效
    void blurBackground(int radius);

    //设置控件是否可见
    void setVisibility(int visibility);
    int getVisibility();
    void setEnabled(bool enabled);
    bool isEnabled();
    void setId(int id);
    int getId();
    void setTag(unsigned long objTag);
    unsigned long getTag();
    void setDirection(int direction); //设置方向，用于列表控件
    int getDirection(); //获取方向，用于列表控件

    void setBackgroundBitmap(Bitmap& bitmap, int x, int y);
    void removeBackgroundBitmap();
    void setBackgroundColor(int color);
    bool isClickable();
    void setClickable(bool clickable);
    bool isScrollable();
    void setScrollable(bool scrollable);
    void setOnTouchListener(OnTouchListener& listener);
    void setOnClickListener(OnClickListener& listener);
    void invalidate();
    void invalidateNotify(); //异步刷新控件，解决部分界面显示异常问题
    void statusChangedNotify(int flag, int value); //异步通知控件状态改变
    virtual bool onTouchEvent(MotionEvent& event);
    bool isReleasable();
    bool autoRelease();
    //@method 设置扩展数据
    void setExtendData(void* data);
    //@method 获取扩展数据
    void* getExtendData();
    //@method void draw(Canvas& canvas)
    //＠description 将该控件绘制到指定画布上，默认使用该控件的坐标
    virtual void draw(Canvas& canvas);
    //@method void draw(Canvas& canvas, int x, int y);
    //＠description 将该控件绘制到指定画布上，并指定要绘制该控件的坐标
    virtual void draw(Canvas& canvas, int x, int y);
    //@method 停止惯性滑动
    virtual void stopSettling();

    //get button pointer from window handle
    static View* getViewFromHWND(HWND hwnd) {
        return (View*)GetWindowAdditionalData(hwnd);
    }
    //@method 设置不响应点击的区域
    void setNonInteractiveRect(Rect rect);
    //@method 判断坐标是否在不可交互区域
    bool pointInNonInteractiveRect(int x, int y);
    int getScrollState();
    //@method 设置是否支持惯性滑动（脱手后惯性滑动一段距离后才停下来）
    void setSettling(bool enable);
    //@method 设置控件是否在视频背景上
    void setOnVideoBackground(bool isOn);
    //@method 是否在视频背景上
    bool isOnVideoBackground();
    //@method 设置是否开启大范围滑动缓冲
    void setSlideBufferEnable(bool enable);

    static void registerViewControl();

    static void unregisterViewControl();

    //button control proc
    static LRESULT ViewControlProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

   protected:
    virtual void onDraw(Canvas& cavas);
    virtual void onAttachedToWindow();
    virtual void onDetachedFromWindow();
    virtual void onSizeChanged(int w, int h, int oldW, int oldH);
    virtual void onClicked();
    virtual void onNotify(int notifyId, void* data);
    virtual void onTouched(MotionEvent& event);
    virtual void onScrolled(MotionEvent& event);
    virtual bool onKeyDown(int keyCode, KeyEvent& keyEvent);
    virtual bool onKeyUp(int keyCode, KeyEvent& keyEvent);
    virtual bool onKeyLongPress(int keyCode, KeyEvent& keyEvent);
    virtual void onStatusChanged(int flag, int value);
    virtual void onFocusChanged(bool isFocus);

    int onViewControlProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    void updateWindow(bool forceRepaint);
    //@method 是否触摸中
    bool isTouching();
    //@method 此次Touch Down后是否发生过滑动
    bool isScorlled();
    //@method 开始惯性滑动
    void startSettlingTimer();

    //父组件的窗口句柄
    HWND mParentHwnd = NULL;
    //按钮组件的窗口句柄
    HWND mHwnd = NULL;

    int mX = 0;
    int mY = 0;
    int mWidth = 0;
    int mHeight = 0;
    int mVisibility = VISIBLE;

    Bitmap* mBackgroundBitmap = nullptr;
    int mBackgroundBitmapX = 0;
    int mBackgroundBitmapY = 0;

    int mBackgroundColor = 0;
    int mId = 0;

    int mScrollGap = 0; //滑动距离
    int mScrollDirection = SCROLL_NONE; //滑动方向
    int mScrollState = SCROLL_STATE_IDLE; //滑动状态
    MotionEvent mMotionEventDown;
    MotionEvent mMotionEventUp;
    MotionEvent mMotionEventOnDraw; //控件绘制时的MotionEvent
    int mScrollHorizontalSpeed = 0; //水平滑动速度, 像素值/秒
    int mScrollVerticalSpeed = 0; //垂直滑动速度, 像素值/秒
    Timer mSettlingTimer;
    int mSettlingAcc = 0; //滑动时加速度
    bool mEnableSettling = false;  //是否打开惯性滑动
    int mScrollGapOnDraw = 0; //onDraw时的滑动距离，记录目前画面绘制时的mScrollGap

    bool mIsStatusChanged = false;  //状态改变标志，某些widget需要根据这个标志做一些处理
    MotionEvent mMotionEvent;
    int mDirection = View::DIRECTION_VERTICAL; //控件方向，用于列表控件
    bool mIsEnabled = true; //是否使能
    bool mIsCareMove = false; //是否关注MOVE事件，例如有触摸中状态的控件需要关注
    bool mIsFocus = false; //是否得到焦点
    bool mIsOnVideoBackground = false; //是否在视频背景上
    bool mIsSlideBufferEnabled = false; //是否开启滑动缓冲，设置为true，有效优化滑动时，画面断层问题

   private:
    void setFlags(int flags, int mask);

    Canvas* mCanvas = nullptr;
    OnTouchListener* mOnTouchListener = nullptr;
    OnClickListener* mOnClickListener = nullptr;
    Bitmap* mEffectBackgroundBitmap = nullptr; //动态效果背景图，例如模糊
    int mEffectBlurBackgroundRadius = 0; //动态模糊半径
    Point mTouchPointCur;
    bool mIsTouchDown = false;
    bool mIsTouchMove = false; //是否发生过滑动
    bool mIsScrollable = false; //是否可滑动
    int mViewFlags = 0;
    View* mParent = nullptr;
    unsigned long mObjTag = 0;
    std::atomic<bool> mDisposable;
    Rect mNonInteractiveRect;
    void* mExtendData = nullptr;
    bool mHadSetSlideBufferEnable = false; //是否开启过滑动缓冲
};

#endif /* CPP_VIEW_H */
